package one.stand.util;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * @author cjr
 */
public class OneListUtil {
    public static boolean isNotEmpty(List list) {
        return Objects.nonNull(list) && list.size() > 0;
    }

    public static boolean isEmpty(List list) {
        return Objects.isNull(list) || list.size() <= 0;
    }

    public static <T> void executeGroup(List<T> list, Consumer<List<T>> consumer, int size) {
        if (isEmpty(list)) {
            return;
        }

        if (list.size() <= size) {
            consumer.accept(list);
        } else {
            List<T> listBatch = Lists.newArrayListWithExpectedSize(size);
            for (T phone : list) {
                listBatch.add(phone);
                if (listBatch.size() == size) {
                    consumer.accept(listBatch);
                    listBatch.clear();
                }
            }
            if (listBatch.size() > 0) {
                consumer.accept(listBatch);
            }
        }
    }

    public static <T> List<T> toList(String str, Function<String, T> function) {
        if (StringUtils.isBlank(str)) return null;

        String[] strArray = StringUtils.split(str, ",");
        List<T> list = Lists.newArrayList();
        for (String stra : strArray) {
            list.add(function.apply(stra));
        }
        return list;
    }

    public static <T, K> List<T> group(List<T> list, Predicate<T> isParent, Function<T, K> id,
                                       Function<T, K> parentId, BiConsumer<T, T> childList) {
        if (isEmpty(list)) return list;

        Map<K, Integer> parentIds = Maps.newHashMap();
        int i = 0;
        List<T> groupList = Lists.newArrayList();
        for (T entity : list) {
            if (isParent.test(entity)) {
                parentIds.put(id.apply(entity), i++);
                groupList.add(entity);
            }
        }
        for (T entity : list) {
            if (!isParent.test(entity)) {
                int parentIndex = parentIds.get(parentId.apply(entity));
                childList.accept(groupList.get(parentIndex), entity);
            }
        }
        return groupList;
    }

    public static <T, K, R> List<R> group(List<T> list, Predicate<T> isParent, Function<T, K> id,
                                          Function<T, K> parentId, BiConsumer<R, R> childList,
                                          Function<T, R> parentFunction, Function<T, R> childFunction) {
        if (Objects.isNull(list)) return null;
        List<R> groupList = Lists.newArrayList();
        if (list.size() <= 0) return groupList;

        Map<K, Integer> parentIds = Maps.newHashMap();
        int i = 0;
        for (T entity : list) {
            if (isParent.test(entity)) {
                R r = parentFunction.apply(entity);
                parentIds.put(id.apply(entity), i++);
                groupList.add(r);
            } else {
                int parentIndex = parentIds.get(parentId.apply(entity));
                R r = childFunction.apply(entity);
                childList.accept(groupList.get(parentIndex), r);
            }
        }
        return groupList;
    }
}
